import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lenovo
 * Date: 2022-08-14
 * Time: 10:21
 */
public class MyArrayList {
    //底层是数组
    int[] elem;
    //初始容量
    public static final int DEFAILT_CAPACITY = 4;
    //记录当前数组里的元素个数和可存放元素的位置
    int usedsize = 0;
//构造方法
    MyArrayList() {
        this.elem = new int[DEFAILT_CAPACITY];
    }

    //打印顺序表
    public void display() {
        //空表
        if(usedsize == 0){
            System.out.println("空表");
            return;
        }
        //循环遍历表里的每个元素
        for (int i = 0; i < usedsize; i++) {
            System.out.print(elem[i]+" ");
        }
        System.out.println();
    }

    /***
     * 增加:尾插 头插 任意位置插
     * 判满 检查index是否合法
     * @param elem
     * @return
     */

    //尾插
    //判满
    private boolean isFull(int[] elem) {
        if (usedsize == elem.length) {
            return true;
        }
        return false;

    }

    public void lastAdd(int val) {
        //判满
        if (isFull(this.elem)) {
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        //在usedsize处插入就是尾插
        elem[usedsize] = val;
        //成功插入后元素个数++
        usedsize++;
    }

    //头插
    //从后面开始往后搬动,避免后面的元素被前面的元素给覆盖
    private void lastLastMove(int[] elem, int i, int j) {
        elem[j] = elem[i];

    }

    public void firstAdd(int val) {
        //判满
        if (isFull(this.elem)) {
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        int i;
        //usedsize即是当前数组里元素个数的数量,又是尾插可以插入元素的位置,i=0处的元素也得往后移
        for (i = usedsize - 1; i >= 0; i--) {
            //从后面开始往后搬动
            lastLastMove(elem, i, i + 1);
        }
        //移动完毕之后,下标为0处的位置空了出来
        elem[0] = val;
        //数量++
        usedsize++;
    }

    //任意位置插入
    //判断index是否合法
    //在usedsize处是可以尾插的,但是大于usedsize是不行的,因为数据结构里规定,插入的位置处是必须有数据前驱的
    private boolean isLegalIndex(int index) {
        if (index < 0 || index > usedsize) {//usedsize可以插入
            return false;
        }
        return true;
    }

    public void  indexAdd(int index, int val) {
        //判断index是否合法
        if (!isLegalIndex(index)) {
            throw new RuntimeException("index不合法");
        }
        //判满
        if (isFull(this.elem)) {
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        //后面有空位置(usedsize处),从后往前移动,避免元素被覆盖;index处的元素也得移动,因为是在index处插入
        for (int i = usedsize - 1; i >= index; i--) {
            lastLastMove(elem, i, i + 1);
        }
        //在index处插入
        elem[index] = val;
        //数量++
        usedsize++;
    }


    /***
     * 查: findHave查内容并且返回第一次出现的下标  -----怎么查出所有关键字为val的下标??? 目前想法是用一个数组记录记录下所有为val的下标 然后返回一个数组下标
     * findIndex插下标
     * 检查index的合法性
     */
    //查内容
    public int findHave(int val) {
        //空表
        if(usedsize == 0){
            System.out.println("空表");
            return 0;
        }
        for (int i = 0; i < usedsize; i++) {
            if (elem[i] == val) {
                return i;
            }
        }
        return -1;
    }

    //查下标
    //检查index合法性
    //这里并不是用来帮助增加元素来判断index是否合法,而是在遍历数组,所以index是不能=usedsize的,usedsize记录了元素的个数和表示尾插法的位置
    private boolean checkIndex(int index) {
        if (index < 0 || index >= usedsize) {
            return false;
        }
        return true;
    }
/*
查找下标处的元素:随机访问
 */
    public int findIndex(int index) {
        //空表
        if(usedsize == 0){
            System.out.println("空表");
            return -1;
        }
        //检查index合法性
        if (!checkIndex(index)) {
            throw new RuntimeException("查询时index不合法,注意这里index不能等于useds ");
        }
        //index合法,直接返回index处的元素
        return elem[index];
    }

    /***
     * 改
     */
    public void change(int index, int val) {
        //空表
        if(usedsize == 0){
            System.out.println("空表");
            return;
        }
        //检查index的合法性
        if (!checkIndex(index)) {
            throw new RuntimeException("修改时index不合法,注意这里index不能等于useds");
        }
        //index合法,直接用val将index处原先的元素给覆盖
        elem[index] = val;
    }

    /**
     * 删 deleteHave删除第一次出现的内容 -----怎么一次性删除全部为val的关键字???
     */

    public void deleteHave(int val) {
        //空表
        if(usedsize == 0){
            System.out.println("空表");
            return;
        }
        //index用来记录val在数组里的下标
        int index = -1;
        //遍历一遍数组,查找是否有val
        for (int i = 0; i < usedsize; i++) {
            if (elem[i] == val) {
                //找到了,将val的下标用index存储起来
                index = i;
                break;
            }
        }
        //1.遇到break跳出来
        if (index != -1) {
           //删除 类似于图书系统 往前移动,从最后面的元素开始,i<usedsize-1,防止越界访问
            //如果i<usedsize,当i=usedsize-1时,elem[i] =elem[i+1],elem[i+1]=elem[usedsize],
            // 而elem[usedsize]是没有值的,同时elem[usedsize]已经数组越界了
            for (int i = index; i <usedsize-1 ; i++) {
                elem[i] =elem[i+1];
            }
            //删除成功数量--
            usedsize--;

        } else {//2.循环走完跳出来
            System.out.println("没有" + val + "这个值");
        }

    }
    //size
    public int size(){
        return usedsize;
    }
    //清空
    public void clean(){
        usedsize = 0;
    }
}
